`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: PSU
// Engineer: Raviraj Kokil
// 
// Create Date: 03/07/2015 03:18:08 PM
// Design Name: 
// Module Name: motor_driver
// Project Name: project4
// Target Devices: Artix 7
// Tool Versions: Vivado 2014.4
// Description: 
//		This file implements the open loop control for motor driver
//		Speed can be controlled by changing the clock_divider value.
//		Direction can be switched by changing direction input
//		Motor can be enabled/disabled using the enable button
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module motor_driver(
	// inputs
    input sysclk,					// system clock
    input sysreset_n,				// system reset
    input direction,				// rotation direction 0 = clockwise, 1 = anticlockwise
    input enable,					// motor_out enable
	// outputs
    output div_clk,					// output div_clk for monitoring
    output reg [5:0] motor_out		// motor_out to drive Mosfets/Driver IC
);

// FSM State encoding
parameter [2:0] OFF     = 3'd0,
                STEP1   = 3'd1,
                STEP2   = 3'd2,
                STEP3   = 3'd3,
                STEP4   = 3'd4,
                STEP5   = 3'd5,
                STEP6   = 3'd6;

// Parameters to denote pull up/pull down ON or complete H-bridge OFF
parameter [1:0] PU_ON   = 2'b11,
                PD_ON   = 2'b10,
                H_OFF   = 2'b00;

parameter CLOCKWISE     = 1'b0;

// default clock divider
parameter [31:0] CLOCK_DIVIDER = 32'd10_000_000;

reg [2:0] state, next_state;		// state registers
reg [31:0] div_counter;				// counter for clock divide
reg i_div_clk;						// intermediate divided clock

assign div_clk = i_div_clk;			// internal to external div_clk connection

always @(posedge sysclk) begin
    if (!sysreset_n) begin
        div_counter <= 32'h0;
        i_div_clk   <= 1'b0;
    end
    else begin
		// Following logic generates 1 clock pulse every CLOCK_DIVIDER no of cycles
		// Thereby clock is divided as required
        if (div_counter < (CLOCK_DIVIDER - 1'b1)) begin
            i_div_clk   <= 1'b0;
            div_counter <= div_counter + 1'b1;
        end
        else begin
            i_div_clk   <= 1'b1;
            div_counter <= 32'h0;
        end
    end
end

// State transition logic - notice that i_div_clk is used 
always @(posedge i_div_clk) begin
    if (!sysreset_n) begin
        state <= OFF;
    end
    else begin
        state <= next_state;
    end
end

// next state logic
always @(*) begin
    case(state)
        OFF     : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP1; 
                end
                else begin
                    next_state = STEP6;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP1   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP2; 
                end
                else begin
                    next_state = STEP6;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP2   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP3; 
                end
                else begin
                    next_state = STEP1;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP3   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP4; 
                end
                else begin
                    next_state = STEP2;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP4   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP5; 
                end
                else begin
                    next_state = STEP3;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP5   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP6; 
                end
                else begin
                    next_state = STEP4;
                end
            end
            else begin
                next_state = OFF;
            end
        end

        STEP6   : begin
            if (enable) begin
                if (direction == CLOCKWISE) begin
                    next_state = STEP1; 
                end
                else begin
                    next_state = STEP5;
                end
            end
            else begin
                next_state = OFF;
            end
        end
        
        default : begin
            next_state = OFF;
        end
    endcase
end


// output logic
always @(*) begin
    case(state)
        OFF     : begin
            motor_out = {H_OFF, H_OFF, H_OFF};	// 6'b00_00_00
        end

        STEP1   : begin
            motor_out = {H_OFF, PD_ON, PU_ON};	// 6'b00_10_11
        end

        STEP2   : begin
            motor_out = {PD_ON, H_OFF, PU_ON};	// 6'b10_00_11
        end

        STEP3   : begin
            motor_out = {PD_ON, PU_ON, H_OFF};	// 6'b10_11_00
        end

        STEP4   : begin
            motor_out = {H_OFF, PU_ON, PD_ON};	// 6'b00_11_10
        end

        STEP5   : begin
            motor_out = {PU_ON, H_OFF, PD_ON};	// 6'b11_00_10
        end

        STEP6   : begin
            motor_out = {PU_ON, PD_ON, H_OFF};	// 6'b11_10_00
        end

        default : begin
            motor_out = {H_OFF, H_OFF, H_OFF};	// 6'b00_00_00
        end
    endcase
end
    
endmodule
